 <!doctype html>
<head>
<meta charset="UTf-8" />
<title>ShinyTouch/JS</title>
<script src="perspective.js" async></script>
<script src="polyfills.js"></script>
<script src="calibration_manual.js"></script>
<script src="calibration_auto1.js"></script>
<script type="text/javascript">
tracking_algorithms || (tracking_algorithms = {});
calibration_algorithms || (calibration_algorithms = {});
update_sequences || (update_sequences = []);

update_sequences.remove = function(func) {
	var pos = update_sequences.indexOf(func);
	
	if (pos < 0) {
		throw new ReferenceError("function not found");
	}
	
	update_sequences.splice(pos,1);
}

function $(id){return this.document.getElementById(id);}
var video, output, draw;
window.onload = function() {
	video = $("input");
	output = $("output");
	draw = $("draw");
	
	output.getContext("2d").strokeStyle="#0ff";
		
	support();
} 
function support(){
	var conditions = [

		navigator.getUserMedia, //shimmed
		window.Uint8ClampedArray, //support for getImageData :)
		document.querySelector,
		(
			document.exitFullscreen ||
			document.cancelFullScreen || 
			document.mozCancelFullScreen || 
			document.webkitCancelFullscreen ||
			document.webkitCancelFullScreen ||
			document.webkitExitFullscreen
		)
	], opt = [0,0,0,1];
		
	var section = $("support").getElementsByTagName("li");
	var supported = true;
	Array.prototype.forEach.call(section,function(el, i){
		if (conditions[i]) {
			el.style.color = "green";
		} else {
			if (!opt[i]) {
				el.style.color = "red";
				supported = false;
			}
			else {
				el.style.color = "#FF8000";
			}
		}
	});
	if (supported) {
		$("support-status").textContent = "\u2713 Your browser is supported!";
		$("support-status").style.color = "green";
	} else {
		$("support-status").textContent = "\u2717 Your browser is not supported!";
		$("support-status").style.color = "red";
	}
}
//function createBlob
function init() {
	document.getElementsByClassName('cover')[0].style.display = 'none';
	
	getUserMedia({video:true},function(stream){
		console.log(stream);
		var bloburl = window.URL.createObjectURL(stream);
		console.log(bloburl);
		window.stream = stream;
		video.src = bloburl;
		
		update();
	},function(e){
		alert("Error! Did you deny permissions?");
		console.error(e);
	});
}
function update() {
	var ctx = output.getContext("2d"), i;
	ctx.drawImage(video,0,0,output.width,output.height);
	ctx.beginPath();
	
	const RECT_SIZE = 10;
	
	var corners = ["tl", "tr", "br", "bl"];
	corners.forEach(function(el,i) {
		var curel = quad[el];
		if (curel) {
			ctx.strokeRect(curel[0] - RECT_SIZE/2,
			               curel[1] - RECT_SIZE/2,
						   RECT_SIZE,
						   RECT_SIZE);
			var nextel = quad[ corners[ (i+1)%4 ] ];
			if (nextel) {
				ctx.moveTo(curel[0],curel[1]);
				ctx.lineTo(nextel[0],nextel[1]);
				ctx.stroke();
			}
		}
	});
	ctx.closePath();
	
	update_sequences.forEach(function(el){ el(); });
	
	window.requestAnimationFrame(update);
}
var quad = {
	tl: null,
	tr: null,
	br: null,
	bl: null,
	
	left  : null,
	right : null,
	top   : null,
	bottom: null,
	
	toprate   : null,
	bottomrate: null
};
var calibration_options = {
	screen_width: null,
	screen_height: null,
	current_algorithm: null
}
var tracking_options = {
	blank_screen: null,
	current_algorithm: null
}
function calculateQuad() {
	quad.left   = Math.min(quad.tl[0],quad.bl[0]);
	quad.right  = Math.max(quad.tr[0],quad.br[0]);
	quad.top    = Math.min(quad.tl[1],quad.tr[1]);
	quad.bottom = Math.max(quad.bl[1],quad.br[1]);
	
	quad.width  = quad.right  - quad.left;
	quad.height = quad.bottom - quad.top;
    
	quad.toprate    = (quad.tl[1]-quad.tr[1])/quad.width  //rate of top change
	quad.bottomrate = (quad.bl[1]-quad.br[1])/quad.width; //rate of bottom change
}
function calibrate(algorithm) {

	var win = window.open("calibrate3.html?" + algorithm,"calibrate","toolbar=no,width=800,height=600");
	
	// redundant but owell
	calibration_options.current_algorithm = algorithm;
}
function track(algorithm) {
	tracking_options.current_algorithm = algorithm;
}
function imageLog(imageData,title,point) {
	var w = imageData.width, h = imageData.height;
	
	var canvas = document.createElement("canvas"),
	    ctx = canvas.getContext("2d");
	canvas.width = imageData.width;
	canvas.height = imageData.height;
	
	ctx.putImageData(imageData,0,0);
	
	if (point) {
		const RECT_SIZE = 10;
		ctx.strokeStyle = "#0ff";
		ctx.strokeRect(point[0] - RECT_SIZE/2,
        	               point[1] - RECT_SIZE/2,
		               RECT_SIZE,
		               RECT_SIZE);
	}	
	
	var data = canvas.toDataURL("image/png");
	
	var image = new Image();
	image.src = data;
	image.title = title;
	$("imageLog").appendChild(image);
	
	//$("imageLog").appendChild(canvas);
}
function captureImageSequence(video,INTERVAL,CAPTURE_ATTEMPTS,oncaptureeach,oncomplete) {
	
	var pixelDatas = [];
	for (var i=0;i<CAPTURE_ATTEMPTS;i++) {
		(function(_i) {
			setTimeout(function(){
				var tempCanvas = document.createElement("canvas"),
					tempCtx = tempCanvas.getContext("2d");
			
				tempCanvas.width = video.videoWidth, tempCanvas.height = video.videoHeight;
				tempCtx.drawImage(video,0,0);
			
				var capturedImage = tempCtx.getImageData(0,0,tempCanvas.width,tempCanvas.height);
			
				pixelDatas.push(capturedImage);
			
				setTimeout(oncaptureeach.bind(null,capturedImage,_i),0);
			}, _i * INTERVAL);
		}(i));
	}
	setTimeout(function() {
		oncomplete(pixelDatas);
	},INTERVAL * CAPTURE_ATTEMPTS);
}
</script>
<style>
body {
	font-family: sans-serif;
	/*margin:0px;*/
}
#draw {
	border: 1px solid black;
}
#input {
	width:320px;
	height:240px;
}
#draw {
}
#info {
	display:inline-block;
	position:relative;
	background-color:white;
	z-index:10;
	border-radius:20px;
	border:10px solid #BBB;
	margin:30px auto;
	width:30%;
	padding:10px;
	text-align:left;
	cursor:auto;
}
.cover {
	text-align: center;
	position:absolute;
	left:0px;
	top:0px;
	width:100%;
	height:100%;
	z-index:9;
	background-color:rgba(200,200,200,0.8);
	cursor:default;
}
</style>
</head>

<body>
<div class="cover">
<section id="info">
<header><h1>ShinyTouch/JS</h1></header>
Hi there! This is a non-working in-development prototype of
<a href="shinytouch-js.googlecode.com" target="_blank">ShinyTouch/JS</a>.

<h2>Required stuff:</h2>
<ul id="support">
<li>getUserMedia API</li>
<li>&lt;canvas&gt; getImageData</li> <!-- polyfilled Uint8ClampedArray -->
<li>querySelector</li>
<li>Fullscreen mode (optional)</li>
</ul>
<span id="support-status">Please waits...</span>
<button value="Close" onclick="init()">Close</button>
<p>
At the time of writing, there are only a couple of places where the getUserMedia API is available: check 
<a href="http://caniuse.com/#feat=stream" target="_blank">caniuse.com</a> for a list of stable browsers that support it.
However, it has been tested using Google Chrome 21+ and Opera 12+.

</p>
<p>
<b>If you suffer from epilepsy or have experienced seizures, please be aware that the automatic calibration process
   may involve quickly flashing colors on the entire monitor screen.</b></p>
</section>
</div>
<section id="container">
<video autoplay id="input" style="display:none"></video>
<!-- I'm using TABLES? lol -->
<table style="border-width:1px;border-spacing:0px">
<tr><!--<th>Camera view</th>--><th>Output</th><th>Draw view</th></tr>
<tr>
<!--
<td>
<video autoplay id="input" width="320" height="240"></video>
</td>
-->
<td>
<canvas id="output" width="480" height="360"></canvas>
</td><td>
<canvas id="draw" width="160" height="120"></canvas>
</td>
</tr>
</table>

<div id="imageLog"></div>
</section>

<section>
<select id="calibration-type">
<option value="auto1">automatic (1)</option>
<option value="manual">Manual</option>
</select>
<button onclick="calibrate($('calibration-type').value)">Begin calibration</button>

<br /><br />

<select id="tracking-type">
<option value="1">one</option>
</select>
<button onclick="track($('tracking-type').value">Begin detection</button>
</section>
</body>
